import akka.actor.AbstractActor
import akka.actor.ActorRef
import akka.actor.Props
import com.google.protobuf.MessageLite
import io.netty.bootstrap.Bootstrap
import io.netty.channel.Channel
import robotAi.Robot
import robotAi.createTestAi

class CountActor(var count: Int, var b: Bootstrap) : AbstractActor() {
    companion object {
        fun Props(robotCount: Int, b: Bootstrap): Props {
            return Props.create(CountActor::class.java, robotCount, b)
        }
    }

    override fun preStart() {
        super.preStart()
        createRobot()
    }

    private val robotMap: MutableMap<Channel, ActorRef> = mutableMapOf()
    private var robots: MutableList<ActorRef> = mutableListOf()  // 正在运行的机器人队列
    private var currentRobotCount = 0;
    override fun createReceive(): Receive {
        return receiveBuilder()
                .match(RunMsg::class.java) {
                    runRobot()
                }
                .match(DelMsg::class.java) {
                    currentRobotCount--;
                    if (currentRobotCount <= 0) {
                        isFinish = true
                    }
                }
                .match(ConnectMsg::class.java) { m ->
                    connect(m.ch, m.ref)
                }
                .match(RecMsg::class.java) { m ->
                    rec(m.ch, m.msgId, m.msg)
                }
                .build()
    }

    private fun createRobot() {
        for (i in 0 until this.count) {
            var ref = system.actorOf(RobotActor.props(b, Robot(i, ::createTestAi)))
            robots.add(ref)
        }
        currentRobotCount = count
    }

    private fun runRobot() {
        for (ref in robots) {
            ref.tell(RobotActor.Run(), ActorRef.noSender())
        }
    }

    private fun rec(ch: Channel, msgId: Int, msg: MessageLite) {
        val ref = robotMap.get(ch)
        if (ref != null) {
            ref.tell(RobotActor.MsgResponder(msgId, msg), ActorRef.noSender())
        }
    }

    private fun connect(ch: Channel, ref: ActorRef) {
        robotMap.put(ch, ref)
    }

    class ConnectMsg(val ch: Channel, val ref: ActorRef)
    class RunMsg

    class DelMsg

    class RecMsg(val ch: Channel, val msgId: Int, val msg: MessageLite)
}